using System;
using System.Runtime.Serialization;
using System.Data;
using Widgetsphere.Core.DataAccess;
using ACME.Northwind.Business.Objects;
using ACME.Northwind.Business.Objects.Components;
using ACME.Northwind.Business.Views;
using ACME.Northwind.Business.StoredProcedures;
using ACME.Northwind.Domain.Objects;
using ACME.Northwind.Domain.Views;
using ACME.Northwind.Domain.StoredProcedures;

//Add the namespaces so they will always exist even if the objects do not
namespace ACME.Northwind.Business.Views
{
	internal class X { }
}
namespace ACME.Northwind.Domain.Views
{
	internal class X { }
}
namespace ACME.Northwind.Business.Objects
{
	internal class X { }
}
namespace ACME.Northwind.Business.Objects.Components
{
	internal class X { }
}
namespace ACME.Northwind.Business.Objects.Composites
{
	internal class X { }
}
namespace ACME.Northwind.Domain.Objects
{
	internal class X { }
}
namespace ACME.Northwind.Domain.Objects.Components
{
	internal class X { }
}
namespace ACME.Northwind.Business.Rules
{
	internal class X { }
}
namespace ACME.Northwind.Business.StoredProcedures
{
	internal class X { }
}

namespace ACME.Northwind.Business.SelectCommands
{
	internal class X { }
}

namespace ACME.Northwind.Domain.StoredProcedures
{
	internal class X { }
}
namespace ACME.Northwind.Business
{
		/// <summary>
		/// The container for all object collections.
		/// </summary>
	[System.ComponentModel.DesignerCategoryAttribute("code")]
	[Serializable()]
	public class SubDomain : SubDomainBase
	{

		#region Constructors
		/// <summary>
		/// The constructor for the subdomain.
		/// </summary>
		public SubDomain(string modifier) : base(modifier){}
		/// <summary>
		/// The constructor for the subdomain.
		/// </summary>
		public SubDomain():base(){}
		#endregion 

		#region GetCollection

		/// <summary>
		/// Get a business collection in this subdomain
		/// </summary>
		public T GetCollection<T>() where T : IBusinessCollection
		{
			if (false) {}
			else if (typeof(T) == typeof(CategoryCollection))
				return (T)this[Collections.CategoryCollection];
			else if (typeof(T) == typeof(CustomerCustomerDemoCollection))
				return (T)this[Collections.CustomerCustomerDemoCollection];
			else if (typeof(T) == typeof(CustomerDemographicCollection))
				return (T)this[Collections.CustomerDemographicCollection];
			else if (typeof(T) == typeof(CustomerCollection))
				return (T)this[Collections.CustomerCollection];
			else if (typeof(T) == typeof(EmployeeCollection))
				return (T)this[Collections.EmployeeCollection];
			else if (typeof(T) == typeof(EmployeeTerritoryCollection))
				return (T)this[Collections.EmployeeTerritoryCollection];
			else if (typeof(T) == typeof(OrderDetailCollection))
				return (T)this[Collections.OrderDetailCollection];
			else if (typeof(T) == typeof(OrderCollection))
				return (T)this[Collections.OrderCollection];
			else if (typeof(T) == typeof(ProductCollection))
				return (T)this[Collections.ProductCollection];
			else if (typeof(T) == typeof(RegionCollection))
				return (T)this[Collections.RegionCollection];
			else if (typeof(T) == typeof(ShipperCollection))
				return (T)this[Collections.ShipperCollection];
			else if (typeof(T) == typeof(SupplierCollection))
				return (T)this[Collections.SupplierCollection];
			else if (typeof(T) == typeof(TerritoryCollection))
				return (T)this[Collections.TerritoryCollection];
			return default(T);
		}
		#endregion 

		#region SubDomainBase Implementation

		/// <summary>
		/// Deterines if the connection uses the web service or connects directly to the database.
		/// </summary>
		[Obsolete("This property no longer applies.")]
		protected override bool DirectConnect
		{
			get
			{
				return ConfigurationValues.GetInstance().DirectConnect;
			}
		}

		/// <summary>
		/// The web service URL end point.
		/// </summary>
		[Obsolete("This property no longer applies.")]
		protected override string DataAccessServiceUrl
		{
			get { return ConfigurationValues.GetInstance().DataAccessServiceUrl; }
		}

		/// <summary>
		/// Determines if any object in this container needs to be saved.
		/// </summary>
		public override bool IsDirty
		{
			get
			{
				foreach (DataTable dt in this.Tables)
				{
					foreach (DataRow dr in dt.Rows)
					{
						if (dr.RowState != DataRowState.Unchanged)
							return true;
					}
				}
				return false;
			}
		}

		/// <summary>
		/// Determines the connection string to the database.
		/// </summary>
		public override string ConnectionString
		{
			get { return ConfigurationValues.GetInstance().ConnectionString; }
		}

		/// <summary>
		/// Adds all object collections in this assembly to the subdomain.
		/// </summary>
		protected override void CreateStronglyTypedTables(System.Data.DataSet ds)
		{
			this.EnsureParentExistsOn = false;

			if(ds.Tables.Contains("CategoryCollection"))
			{
				DomainCategoryCollection tmpCollection = (DomainCategoryCollection)ds.Tables["CategoryCollection"];
				this.AddCollection(Collections.CategoryCollection);
				DomainCategoryCollection permanentCollection = (DomainCategoryCollection)this.GetDomainCollection(Collections.CategoryCollection);

				permanentCollection.ProductFilled = tmpCollection.ProductFilled;
			}

			if(ds.Tables.Contains("CustomerCustomerDemoCollection"))
			{
				DomainCustomerCustomerDemoCollection tmpCollection = (DomainCustomerCustomerDemoCollection)ds.Tables["CustomerCustomerDemoCollection"];
				this.AddCollection(Collections.CustomerCustomerDemoCollection);
				DomainCustomerCustomerDemoCollection permanentCollection = (DomainCustomerCustomerDemoCollection)this.GetDomainCollection(Collections.CustomerCustomerDemoCollection);

			}

			if(ds.Tables.Contains("CustomerDemographicCollection"))
			{
				DomainCustomerDemographicCollection tmpCollection = (DomainCustomerDemographicCollection)ds.Tables["CustomerDemographicCollection"];
				this.AddCollection(Collections.CustomerDemographicCollection);
				DomainCustomerDemographicCollection permanentCollection = (DomainCustomerDemographicCollection)this.GetDomainCollection(Collections.CustomerDemographicCollection);

				permanentCollection.CustomerCustomerDemoFilled = tmpCollection.CustomerCustomerDemoFilled;
			}

			if(ds.Tables.Contains("CustomerCollection"))
			{
				DomainCustomerCollection tmpCollection = (DomainCustomerCollection)ds.Tables["CustomerCollection"];
				this.AddCollection(Collections.CustomerCollection);
				DomainCustomerCollection permanentCollection = (DomainCustomerCollection)this.GetDomainCollection(Collections.CustomerCollection);

				permanentCollection.CustomerCustomerDemoFilled = tmpCollection.CustomerCustomerDemoFilled;
				permanentCollection.OrderFilled = tmpCollection.OrderFilled;
			}

			if(ds.Tables.Contains("EmployeeCollection"))
			{
				DomainEmployeeCollection tmpCollection = (DomainEmployeeCollection)ds.Tables["EmployeeCollection"];
				this.AddCollection(Collections.EmployeeCollection);
				DomainEmployeeCollection permanentCollection = (DomainEmployeeCollection)this.GetDomainCollection(Collections.EmployeeCollection);

				permanentCollection.EmployeeTerritoryFilled = tmpCollection.EmployeeTerritoryFilled;
				permanentCollection.OrderFilled = tmpCollection.OrderFilled;
			}

			if(ds.Tables.Contains("EmployeeTerritoryCollection"))
			{
				DomainEmployeeTerritoryCollection tmpCollection = (DomainEmployeeTerritoryCollection)ds.Tables["EmployeeTerritoryCollection"];
				this.AddCollection(Collections.EmployeeTerritoryCollection);
				DomainEmployeeTerritoryCollection permanentCollection = (DomainEmployeeTerritoryCollection)this.GetDomainCollection(Collections.EmployeeTerritoryCollection);

			}

			if(ds.Tables.Contains("OrderDetailCollection"))
			{
				DomainOrderDetailCollection tmpCollection = (DomainOrderDetailCollection)ds.Tables["OrderDetailCollection"];
				this.AddCollection(Collections.OrderDetailCollection);
				DomainOrderDetailCollection permanentCollection = (DomainOrderDetailCollection)this.GetDomainCollection(Collections.OrderDetailCollection);

			}

			if(ds.Tables.Contains("OrderCollection"))
			{
				DomainOrderCollection tmpCollection = (DomainOrderCollection)ds.Tables["OrderCollection"];
				this.AddCollection(Collections.OrderCollection);
				DomainOrderCollection permanentCollection = (DomainOrderCollection)this.GetDomainCollection(Collections.OrderCollection);

				permanentCollection.OrderDetailFilled = tmpCollection.OrderDetailFilled;
			}

			if(ds.Tables.Contains("ProductCollection"))
			{
				DomainProductCollection tmpCollection = (DomainProductCollection)ds.Tables["ProductCollection"];
				this.AddCollection(Collections.ProductCollection);
				DomainProductCollection permanentCollection = (DomainProductCollection)this.GetDomainCollection(Collections.ProductCollection);

				permanentCollection.OrderDetailFilled = tmpCollection.OrderDetailFilled;
			}

			if(ds.Tables.Contains("RegionCollection"))
			{
				DomainRegionCollection tmpCollection = (DomainRegionCollection)ds.Tables["RegionCollection"];
				this.AddCollection(Collections.RegionCollection);
				DomainRegionCollection permanentCollection = (DomainRegionCollection)this.GetDomainCollection(Collections.RegionCollection);

				permanentCollection.TerritoryFilled = tmpCollection.TerritoryFilled;
			}

			if(ds.Tables.Contains("ShipperCollection"))
			{
				DomainShipperCollection tmpCollection = (DomainShipperCollection)ds.Tables["ShipperCollection"];
				this.AddCollection(Collections.ShipperCollection);
				DomainShipperCollection permanentCollection = (DomainShipperCollection)this.GetDomainCollection(Collections.ShipperCollection);

				permanentCollection.OrderFilled = tmpCollection.OrderFilled;
			}

			if(ds.Tables.Contains("SupplierCollection"))
			{
				DomainSupplierCollection tmpCollection = (DomainSupplierCollection)ds.Tables["SupplierCollection"];
				this.AddCollection(Collections.SupplierCollection);
				DomainSupplierCollection permanentCollection = (DomainSupplierCollection)this.GetDomainCollection(Collections.SupplierCollection);

				permanentCollection.ProductFilled = tmpCollection.ProductFilled;
			}

			if(ds.Tables.Contains("TerritoryCollection"))
			{
				DomainTerritoryCollection tmpCollection = (DomainTerritoryCollection)ds.Tables["TerritoryCollection"];
				this.AddCollection(Collections.TerritoryCollection);
				DomainTerritoryCollection permanentCollection = (DomainTerritoryCollection)this.GetDomainCollection(Collections.TerritoryCollection);

				permanentCollection.EmployeeTerritoryFilled = tmpCollection.EmployeeTerritoryFilled;
			}


			this.EnsureParentExistsOn = true;
		}

		#endregion 

		#region Contains

		/// <summary>
		/// Returns the number of loaded items in the specified collection.
		/// </summary>
		internal bool Contains(Collections collection)
		{
			string tableName = collection.ToString();
			return this.Tables.Contains(tableName);
		}

		#endregion 

		#region GetDomainCollection

		/// <summary>
		/// Returns the specified collection as a strongly-typed object. If the collection is not part of the subdomain, it is added.
		/// </summary>
		internal DomainCollectionBase GetDomainCollection(Collections collection)
		{
			string tableName = collection.ToString();
			if(!this.Tables.Contains(tableName))
			{
				AddCollection(collection);
			}
			return base[collection.ToString()];
		}

		#endregion 

		#region AddCollection

		/// <summary>
		/// Adds a collection of the specified type to the subdomain.
		/// </summary>
		public void AddCollection(Collections collection)
		{
			bool oldEc = this.EnforceConstraints;
			this.EnforceConstraints = false;
			switch(collection)
			{
				case Collections.CategoryCollection: this.AddCollection(new DomainCategoryCollection());break;
				case Collections.CustomerCustomerDemoCollection: this.AddCollection(new DomainCustomerCustomerDemoCollection());break;
				case Collections.CustomerDemographicCollection: this.AddCollection(new DomainCustomerDemographicCollection());break;
				case Collections.CustomerCollection: this.AddCollection(new DomainCustomerCollection());break;
				case Collections.EmployeeCollection: this.AddCollection(new DomainEmployeeCollection());break;
				case Collections.EmployeeTerritoryCollection: this.AddCollection(new DomainEmployeeTerritoryCollection());break;
				case Collections.OrderDetailCollection: this.AddCollection(new DomainOrderDetailCollection());break;
				case Collections.OrderCollection: this.AddCollection(new DomainOrderCollection());break;
				case Collections.ProductCollection: this.AddCollection(new DomainProductCollection());break;
				case Collections.RegionCollection: this.AddCollection(new DomainRegionCollection());break;
				case Collections.ShipperCollection: this.AddCollection(new DomainShipperCollection());break;
				case Collections.SupplierCollection: this.AddCollection(new DomainSupplierCollection());break;
				case Collections.TerritoryCollection: this.AddCollection(new DomainTerritoryCollection());break;

			}
			this.EnsureParentRowsExist();
			this.EnforceConstraints = oldEc;
		}

		#endregion

		#region this[]

		/// <summary>
		/// Returns the specified collection in this subdomain.
		/// </summary>
		protected override IBusinessCollection this[Enum collection]
		{
			get
			{
				return (IBusinessCollection)this[(Collections)collection];
			}
		}

		/// <summary>
		/// Returns the specified collection in this subdomain.
		/// </summary>
		public IBusinessCollection this[Collections collection]
		{
			get
			{
				IBusinessCollection businessCollection = null;
				switch(collection)
				{
				case Collections.CategoryCollection: businessCollection = new CategoryCollection((DomainCategoryCollection)this.GetDomainCollection(collection));break;
				case Collections.CustomerCustomerDemoCollection: businessCollection = new CustomerCustomerDemoCollection((DomainCustomerCustomerDemoCollection)this.GetDomainCollection(collection));break;
				case Collections.CustomerDemographicCollection: businessCollection = new CustomerDemographicCollection((DomainCustomerDemographicCollection)this.GetDomainCollection(collection));break;
				case Collections.CustomerCollection: businessCollection = new CustomerCollection((DomainCustomerCollection)this.GetDomainCollection(collection));break;
				case Collections.EmployeeCollection: businessCollection = new EmployeeCollection((DomainEmployeeCollection)this.GetDomainCollection(collection));break;
				case Collections.EmployeeTerritoryCollection: businessCollection = new EmployeeTerritoryCollection((DomainEmployeeTerritoryCollection)this.GetDomainCollection(collection));break;
				case Collections.OrderDetailCollection: businessCollection = new OrderDetailCollection((DomainOrderDetailCollection)this.GetDomainCollection(collection));break;
				case Collections.OrderCollection: businessCollection = new OrderCollection((DomainOrderCollection)this.GetDomainCollection(collection));break;
				case Collections.ProductCollection: businessCollection = new ProductCollection((DomainProductCollection)this.GetDomainCollection(collection));break;
				case Collections.RegionCollection: businessCollection = new RegionCollection((DomainRegionCollection)this.GetDomainCollection(collection));break;
				case Collections.ShipperCollection: businessCollection = new ShipperCollection((DomainShipperCollection)this.GetDomainCollection(collection));break;
				case Collections.SupplierCollection: businessCollection = new SupplierCollection((DomainSupplierCollection)this.GetDomainCollection(collection));break;
				case Collections.TerritoryCollection: businessCollection = new TerritoryCollection((DomainTerritoryCollection)this.GetDomainCollection(collection));break;


				}
				return businessCollection;
			}
		}

	#endregion

	}

	#region Collections Enumeration
	 /// <summary>
	 /// An enumeration of all tables that can be held by this subdomain
	 /// </summary>
	 public enum Collections
	 {
			/// <summary>
			/// Identifies set object set
			/// </summary>
			_NotSet = 0,
			/// <summary>
			/// Identifies the Category table
			/// </summary>
			CategoryCollection = 1,
			/// <summary>
			/// Identifies the CustomerCustomerDemo table
			/// </summary>
			CustomerCustomerDemoCollection = 2,
			/// <summary>
			/// Identifies the CustomerDemographic table
			/// </summary>
			CustomerDemographicCollection = 3,
			/// <summary>
			/// Identifies the Customer table
			/// </summary>
			CustomerCollection = 4,
			/// <summary>
			/// Identifies the Employee table
			/// </summary>
			EmployeeCollection = 5,
			/// <summary>
			/// Identifies the EmployeeTerritory table
			/// </summary>
			EmployeeTerritoryCollection = 6,
			/// <summary>
			/// Identifies the OrderDetail table
			/// </summary>
			OrderDetailCollection = 7,
			/// <summary>
			/// Identifies the Order table
			/// </summary>
			OrderCollection = 8,
			/// <summary>
			/// Identifies the Product table
			/// </summary>
			ProductCollection = 9,
			/// <summary>
			/// Identifies the Region table
			/// </summary>
			RegionCollection = 10,
			/// <summary>
			/// Identifies the Shipper table
			/// </summary>
			ShipperCollection = 11,
			/// <summary>
			/// Identifies the Supplier table
			/// </summary>
			SupplierCollection = 12,
			/// <summary>
			/// Identifies the Territory table
			/// </summary>
			TerritoryCollection = 13,
	}
	#endregion

}
